#include <stdlib.h>
#include "MIApplication.h"
#include "MIUser.h"
#include "MIRole.h"

namespace MIApplication {

int getRole(const Collaboration::MIApplication& app, 
			const ::std::string& role)
{
	unsigned int i;
	for(i=0; i<app.roles.size(); i++)
	{
		if (app.roles[i].name == role)
		{
			return i;
		}
	}

	return -1;
}

int getUser(const Collaboration::MIApplication& app, 
			const ::std::string& user)
{
	unsigned int i;
	for(i=0; i<app.users.size(); i++)
	{
		if (app.users[i].name == user)
		{
			return i;
		}
	}

	return -1;
}

int getComponent(const Collaboration::MIApplication& app, 
				const ::std::string& comp)
{
	unsigned int i;
	for(i=0; i<app.components.size(); i++)
	{
		if (app.components[i].name == comp)
		{
			return i;
		}
	}

	return -1;
}

bool addRole(Collaboration::MIApplication& app, 
			Collaboration::MIRole& role)
{
	if (getRole(app, role.name) == -1)
	{
		app.roles.push_back(role);
		
		return true;
	}

	else
	{
		return false;
	}
}

bool removeRole(Collaboration::MIApplication& app, 
				const ::std::string& role)
{
	unsigned int i;
	Collaboration::MIRole temp;

	for (i = 0; i < app.users.size(); i++)
	{
		if (app.users[i].defaultRole == role)
		{
			return false; //si es rol por defecto no se puede eliminar
		}
	}

	for (i = 0; i < app.roles.size(); i++)
	{
		if (app.roles[i].name == role)
		{
			//intercambiar el escogido por el ultimo
			temp = app.roles[app.roles.size()-1];
			app.roles[app.roles.size()-1] = app.roles[i];
			app.roles[i] = temp;

			//truncar el ultimo elemento
			app.roles.pop_back();
			
			break;
		}
	}

	for (i = 0; i < app.users.size(); i++)
	{
		MIUser::removeAllowedRole(app.users[i], role);
	}

	return true;
}

bool addUser(Collaboration::MIApplication& app, 
			Collaboration::MIUser& user)
{
	if ( (getUser(app, user.name) == -1) &&
		 (getRole(app, user.defaultRole) != -1) )
	{
		app.users.push_back(user);
		
		return true;
	}

	else return false;
}

bool removeUser(Collaboration::MIApplication& app, 
				const ::std::string& user)
{
	Collaboration::MIUser temp;

	int pos = getUser(app, user);
	if (pos != -1)
	{
		//intercambiar el escogido por el ultimo
		temp = app.users[app.users.size()-1];
		app.users[app.users.size()-1] = app.users[pos];
		app.users[pos] = temp;
		
		//truncar el ultimo elemento
		app.users.pop_back();
		
		return true;
	}
	else return false;
}

bool updateUserTime(Collaboration::MIApplication& app, 
					const ::std::string& user)
{
	Collaboration::MIUser aux;
	int pos = getUser(app, user);
	if (pos != -1)
	{
		aux = app.users[pos];
		aux.lastTimeUpdated = time(0);
		app.users[pos] = aux;
		
		return true;
	}
	else return false;
}

::std::string setConnectedUser(Collaboration::MIApplication& app, 
								const ::std::string& user)
{
	Collaboration::MIUser aux;
	
	int pos = getUser(app, user);
	if (pos != -1)
	{
		aux = app.users[pos];
		aux.isOnline = true;
		aux.actualRole = aux.defaultRole;
		
		app.users[pos] = aux;

		return aux.actualRole;
	}
	else
	{
		::std::string vacia;
		return vacia;
	}
}

void setDisconnectedUser(Collaboration::MIApplication& app, 
						const ::std::string& user)
{
	Collaboration::MIUser aux;
	
	int pos = getUser(app, user);
	if (pos != -1)
	{
		aux = app.users[pos];
		aux.isOnline = false;
		
		app.users[pos] = aux;
	}
}

void addComponent(Collaboration::MIApplication& app, 
				Collaboration::MIComponent& comp)
{
	app.components.push_back(comp);
}

void addRoleComponentPermissions(Collaboration::MIApplication& app, 
								const ::std::string& role, 
								const ::std::string& comp, 
								::Ice::Int permissions)
{
	int pos = getRole(app, role);
	if (pos != -1)
	{
		MIRole::setComponentPermissions(app.roles[pos], comp, permissions);
	}
}

void addUserComponentPermissions(Collaboration::MIApplication& app, 
								const ::std::string& user, 
								const ::std::string& comp, 
								::Ice::Int permissions)
{
	int pos = getUser(app, user);
	if (pos != -1)
	{
		MIUser::setComponentPermissions(app.users[pos], comp, permissions);
	}
}

::Ice::Int roleComponentPermissions(Collaboration::MIApplication& app, 
									const ::std::string& role, 
									const ::std::string& comp)
{
	int permiso = -1;
	int pos = getRole(app, role);
	if (pos != -1)
	{
		permiso = MIRole::getComponentPermissions(app.roles[pos], comp);
		if (permiso == -1)
			permiso = app.defaultPermissions;
	}

	return permiso;
}

bool existsRole(const Collaboration::MIApplication& app, 
				const ::std::string& role)
{
	return (getRole(app, role) != -1);
}

bool existsUser(const Collaboration::MIApplication& app, 
				const ::std::string& user)
{
	return (getUser(app, user) != -1);
}

bool existsComponent(const Collaboration::MIApplication& app, 
					const ::std::string& comp)
{
	return (getComponent(app, comp) != -1);
}

bool setActualUserRole(Collaboration::MIApplication& app, 
						const ::std::string& user, 
						const ::std::string& newrole)
{
	int pos_user = getUser(app, user);
	int pos_role = getRole(app, newrole);

	if (pos_user != -1)
	{
		if (pos_role != -1)
		{
			app.users[pos_user].actualRole = newrole;
			return true;
		}
		else return false;
	}
	else return false;
}

bool addUserAllowedRole(Collaboration::MIApplication& app, 
						const ::std::string& user, 
						const ::std::string& newrole)
{
	int pos_usr = getUser(app, user);
	int pos_role = getRole(app, newrole);
	
	if (pos_usr != -1)
	{
		if (pos_role != -1)
		{
			return MIUser::addAllowedRole(app.users[pos_usr], newrole);
		}
		else return false;
	}
	else return false;
}

bool removeUserAllowedRole(Collaboration::MIApplication& app, 
							const ::std::string& user, 
							const ::std::string& role)
{
	int pos = getUser(app, user);
	if (pos != -1)
	{
		return MIUser::removeAllowedRole(app.users[pos], role);
	}
	else return false;
}

Collaboration::ListOfUsers getNonUpdatedUsers(const Collaboration::MIApplication& app)
{
	Collaboration::ListOfUsers v;
	Collaboration::MIUser usr;
	
	long tiempo_margen = 60; //1 minuto de margen
	long tiempo_actual = time(0);
	
	unsigned int i;
	for (i = 0; i < app.users.size(); i++)
	{
		usr = app.users[i];
		if (usr.isOnline && ( ( tiempo_actual - usr.lastTimeUpdated ) > tiempo_margen ))
		{
			v.push_back(usr);
		}
	}

	return v;
}

Collaboration::ListOfStrings getRoleUsers(const Collaboration::MIApplication& app, 
											const ::std::string& role)
{
	unsigned int i;
	Collaboration::ListOfStrings conectados;
	Collaboration::MIUser usr;
	
	for (i = 0; i < app.users.size(); i++)
	{
		usr = app.users[i];
		
		if (usr.isOnline 
			&& !usr.actualRole.empty() 
			&& (usr.actualRole == role))
		{
			conectados.push_back(usr.name);
		}
	}

	return conectados;
}

Collaboration::ListOfUsersAndRoles getConnectedUsers(const Collaboration::MIApplication& app)
{
	unsigned int i;
	
	Collaboration::ListOfUsersAndRoles v;
	Collaboration::MIUser usr;
	
	for (i = 0; i < app.users.size(); i++)
	{
		usr = app.users[i];
		if (usr.isOnline)
		{	
			Collaboration::ListOfStrings vv;
			vv.push_back(usr.name);
			vv.push_back(usr.actualRole);
			
			v.push_back(vv);
		}
	}

	return v;
}

Collaboration::ListOfUsers getConnectedUsersInfo(const Collaboration::MIApplication& app)
{
	unsigned int i;
	Collaboration::ListOfUsers conectados;
	Collaboration::MIUser usr;
	
	for (i = 0; i < app.users.size(); i++)
	{
		usr = app.users[i];
		
		if (usr.isOnline)
		{
			conectados.push_back(usr);
		}
	}

	return conectados;
}

::std::string getActualUserRole(Collaboration::MIApplication& app, 
								const ::std::string& user)
{
	int pos = getUser(app, user);
	if (pos != -1)
	{
		return (app.users[pos].actualRole);
	}
	else
	{
		::std::string vacia; 
		return vacia;
	}
}

::Ice::Int userComponentPermissions(Collaboration::MIApplication& app, 
									const ::std::string& user, 
									const ::std::string& comp)
{
	int permiso = -1;
	int pos = getUser(app, user);
	
	if (pos != -1)
	{
		permiso = MIUser::getComponentPermissions(app.users[pos], comp);
		if (permiso == -1) 
			permiso = app.defaultPermissions;
	}
	
	return permiso;
}

bool setUserComponentPermissions(Collaboration::MIApplication& app, 
								const ::std::string& user, 
								const ::std::string& comp, 
								::Ice::Int permissions)
{
	int pos_user = getUser(app, user);
	int pos_cmp = getComponent(app, comp);
	
	if (( pos_user != -1 ) && ( pos_cmp != -1 ))
	{
		MIUser::setComponentPermissions(app.users[pos_user], comp, permissions);
		
		return true;
	}
	else return false;
}

bool setRoleComponentPermissions(Collaboration::MIApplication& app, 
								const ::std::string& role, 
								const ::std::string& comp, 
								::Ice::Int permissions)
{
	int pos_role = getRole(app, role);
	int pos_cmp = getComponent(app, comp);
	
	if (( pos_role != -1 ) && ( pos_cmp != -1 ))
	{
		MIRole::setComponentPermissions(app.roles[pos_role], comp, permissions);
		
		return true;
	}
	else return false;
}

}
